package ch.nostromo.tiffanys.engines.tiffanys.board.pieces;

import ch.nostromo.lib.util.NosTools;
import ch.nostromo.tiffanys.engines.tiffanys.board.TiffanysBoard;
import ch.nostromo.tiffanys.engines.tiffanys.board.TiffanysMove;
import ch.nostromo.tiffanys.engines.tiffanys.board.pieces.TiffanysPiece;
import ch.nostromo.tiffanys.game.board.Board;

public class TiffanysKing extends TiffanysPiece {

  private static final int myPieceCode = Board.PIECE_KING;

  public static final int MATERIAL_VALUE = 90000;

  public static int getMoveList(long[] board, int currentPosition, int myColor, int oldArrayLength, TiffanysMove[] moves, int[] enemyValues, boolean[] validMoveFields) {
    int arrayLength = oldArrayLength;
    int toField = currentPosition + 1;
    if (validMoveFields[toField]) {
      moves[arrayLength].setMove(currentPosition, toField, myPieceCode);
      moves[arrayLength].hitmove = true;
      moves[arrayLength].hitScore = enemyValues[toField] - MATERIAL_VALUE;
      arrayLength++;
    }

    toField = currentPosition - 1;
    if (validMoveFields[toField]) {
      moves[arrayLength].setMove(currentPosition, toField, myPieceCode);
      moves[arrayLength].hitmove = true;
      moves[arrayLength].hitScore = enemyValues[toField] - MATERIAL_VALUE;
      arrayLength++;
    }

    toField = currentPosition + 10;
    if (validMoveFields[toField]) {
      moves[arrayLength].setMove(currentPosition, toField, myPieceCode);
      moves[arrayLength].hitmove = true;
      moves[arrayLength].hitScore = enemyValues[toField] - MATERIAL_VALUE;
      arrayLength++;
    }

    toField = currentPosition - 10;
    if (validMoveFields[toField]) {
      moves[arrayLength].setMove(currentPosition, toField, myPieceCode);
      moves[arrayLength].hitmove = true;
      moves[arrayLength].hitScore = enemyValues[toField] - MATERIAL_VALUE;
      arrayLength++;
    }

    toField = currentPosition + 11;
    if (validMoveFields[toField]) {
      moves[arrayLength].setMove(currentPosition, toField, myPieceCode);
      moves[arrayLength].hitmove = true;
      moves[arrayLength].hitScore = enemyValues[toField] - MATERIAL_VALUE;
      arrayLength++;
    }

    toField = currentPosition - 11;
    if (validMoveFields[toField]) {
      moves[arrayLength].setMove(currentPosition, toField, myPieceCode);
      moves[arrayLength].hitmove = true;
      moves[arrayLength].hitScore = enemyValues[toField] - MATERIAL_VALUE;
      arrayLength++;
    }

    toField = currentPosition - 9;
    if (validMoveFields[toField]) {
      moves[arrayLength].setMove(currentPosition, toField, myPieceCode);
      moves[arrayLength].hitmove = true;
      moves[arrayLength].hitScore = enemyValues[toField] - MATERIAL_VALUE;
      arrayLength++;
    }

    toField = currentPosition + 9;
    if (validMoveFields[toField]) {
      moves[arrayLength].setMove(currentPosition, toField, myPieceCode);
      moves[arrayLength].hitmove = true;
      moves[arrayLength].hitScore = enemyValues[toField] - MATERIAL_VALUE;
      arrayLength++;
    }

    // castling ... with check test !
    int longRook = 21;
    int shortRook = 28;
    int kingPos = 25;

    if (myColor == Board.OWNER_BLACK) {
      longRook = 91;
      shortRook = 98;
      kingPos = 95;
    }

    // long castling
    if (currentPosition == kingPos && NosTools.checkMask(board[longRook], Board.PIECE_ROOK) && !TiffanysBoard.isMovedField(board[longRook]) && !TiffanysBoard.isMovedField(board[currentPosition]) && TiffanysBoard.isEmptyField(board[longRook + 1])
        && TiffanysBoard.isEmptyField(board[longRook + 2]) && TiffanysBoard.isEmptyField(board[longRook + 3])) {

      // Check for check
      if (!TiffanysPiece.isKingAttacked(board, currentPosition, myColor) && !TiffanysPiece.isKingAttacked(board, currentPosition - 1, myColor) && !TiffanysPiece.isKingAttacked(board, currentPosition - 2, myColor)) {
        moves[arrayLength].setMove(currentPosition, currentPosition - 2, myPieceCode);
        moves[arrayLength].castling = TiffanysMove.CASTLING_LONG;
        moves[arrayLength].castlingRook = longRook;
        arrayLength++;
      }

    }

    // short castling
    if (currentPosition == kingPos && NosTools.checkMask(board[shortRook], Board.PIECE_ROOK) && !TiffanysBoard.isMovedField(board[shortRook]) && !TiffanysBoard.isMovedField(board[currentPosition]) && TiffanysBoard.isEmptyField(board[shortRook - 1])
        && TiffanysBoard.isEmptyField(board[shortRook - 2])) {

      if (!TiffanysPiece.isKingAttacked(board, currentPosition, myColor) && !TiffanysPiece.isKingAttacked(board, currentPosition + 1, myColor) && !TiffanysPiece.isKingAttacked(board, currentPosition + 2, myColor)) {
        moves[arrayLength].setMove(currentPosition, currentPosition + 2, myPieceCode);
        moves[arrayLength].castling = TiffanysMove.CASTLING_SHORT;
        moves[arrayLength].castlingRook = shortRook;
        arrayLength++;
      }
    }

    return arrayLength;

  }

  public static int getHitMoveList(int currentPosition, int oldArrayLength, TiffanysMove[] moves, int[] enemyValues) {
    int arrayLength = oldArrayLength;
    int toField = currentPosition + 1;
    if (enemyValues[toField] != 0) {
      moves[arrayLength].setMove(currentPosition, toField, myPieceCode);
      moves[arrayLength].hitmove = true;
      moves[arrayLength].hitScore = enemyValues[toField] - MATERIAL_VALUE;
      arrayLength++;
    }

    toField = currentPosition - 1;
    if (enemyValues[toField] != 0) {
      moves[arrayLength].setMove(currentPosition, toField, myPieceCode);
      moves[arrayLength].hitmove = true;
      moves[arrayLength].hitScore = enemyValues[toField] - MATERIAL_VALUE;
      arrayLength++;
    }

    toField = currentPosition + 10;
    if (enemyValues[toField] != 0) {
      moves[arrayLength].setMove(currentPosition, toField, myPieceCode);
      moves[arrayLength].hitmove = true;
      moves[arrayLength].hitScore = enemyValues[toField] - MATERIAL_VALUE;
      arrayLength++;
    }

    toField = currentPosition - 10;
    if (enemyValues[toField] != 0) {
      moves[arrayLength].setMove(currentPosition, toField, myPieceCode);
      moves[arrayLength].hitmove = true;
      moves[arrayLength].hitScore = enemyValues[toField] - MATERIAL_VALUE;
      arrayLength++;
    }

    toField = currentPosition + 11;
    if (enemyValues[toField] != 0) {
      moves[arrayLength].setMove(currentPosition, toField, myPieceCode);
      moves[arrayLength].hitmove = true;
      moves[arrayLength].hitScore = enemyValues[toField] - MATERIAL_VALUE;
      arrayLength++;
    }

    toField = currentPosition - 11;
    if (enemyValues[toField] != 0) {
      moves[arrayLength].setMove(currentPosition, toField, myPieceCode);
      moves[arrayLength].hitmove = true;
      moves[arrayLength].hitScore = enemyValues[toField] - MATERIAL_VALUE;
      arrayLength++;
    }

    toField = currentPosition - 9;
    if (enemyValues[toField] != 0) {
      moves[arrayLength].setMove(currentPosition, toField, myPieceCode);
      moves[arrayLength].hitmove = true;
      moves[arrayLength].hitScore = enemyValues[toField] - MATERIAL_VALUE;
      arrayLength++;
    }

    toField = currentPosition + 9;
    if (enemyValues[toField] != 0) {
      moves[arrayLength].setMove(currentPosition, toField, myPieceCode);
      moves[arrayLength].hitmove = true;
      moves[arrayLength].hitScore = enemyValues[toField] - MATERIAL_VALUE;
      arrayLength++;
    }

    return arrayLength;

  }

}